﻿using ControlHelper.Attributes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Creator.Access.Core
{
    [DependOn(typeof(TcpConnectCfg),typeof(TcpCmd))]
    public class TcpOperation : OperationBase
    {

        TcpClient tcp; 
        TcpConnectCfg Tcc => (TcpConnectCfg)ConnectConfig;
         
        [NickName("使用异步读取")]
        public bool UseAsync { get; set; }

        [NickName("读取等待时间", "单位毫秒")]
        public int ReadDelay { get; set; } = 1000;

        public event Action<object> OnAsyncReceivedData;
         

        byte[] buffer = new byte[1024];
        public TcpOperation()
        { 
            tcp = new TcpClient();
            
        }

        private void OnReadCallback(IAsyncResult asyncResult)
        {
           var stream = tcp.GetStream();
            int bytesRead = tcp.GetStream().EndRead(asyncResult);

            if (bytesRead > 0)
            {
                string dataReceived = Encoding.UTF8.GetString(buffer, 0, bytesRead);
        
                OnAsyncReceivedData?.Invoke(dataReceived);
                buffer = new byte[1024];
                // 继续异步读取
                stream.BeginRead(buffer, 0, buffer.Length, OnReadCallback, null);
            }
        }

        public override bool Connect()
        {
            try
            {
                tcp.Connect(Tcc.IP, Tcc.Port);
                if (UseAsync)
                    tcp.GetStream().BeginRead(buffer, 0, buffer.Length, OnReadCallback, null);
                return true;
            }
            catch (Exception ex)
            { 
                throw ex;
            }
            
        }

        public override void Disconnected()
        {
            tcp.Close();
        }

        protected override ResultBase Read(object cmd)
        {
            if(cmd is TcpCmd tc)
            {
                var data = Encoding.UTF8.GetBytes(tc.CommandStr.ToString());
                tcp.GetStream().Write(data, 0, data.Length);
               
                if (UseAsync)
                    return null;
                else
                {
                    byte[] reads = new byte[1024];
                    Thread.Sleep(ReadDelay);
                    tcp.GetStream().Read(reads, 0, reads.Length);
                    tc.Result.Data = Encoding.UTF8.GetString(reads);
                    return tc.Result;
                } 
            }
            return null;
           
        }
    }
}
